import BaseBle from './BaseBle.js'
import util from './util.js'
import {
	BLE_ERR,
	YOUON_LOCK_CONF
} from './constants.js'
export default class YouonBle extends BaseBle {
	constructor(options) {
		super(options);
	}
	async connBleAndNotify(bleName = '') {
		await this.doAuthorize();
		await this.openBluetoothAdapter();
		const device = await this.startDiscoveryPromise('C6:A0:B4:C1:56:95');
		console.log('found deviceId -->', device.deviceId);
		await this.createBLEConnection(device.deviceId);
		await this.setBLEMTU(120);
		const services = await this.getBLEDeviceServices();
		console.log('found services -->', services);
		const characters = await this.getBLEDeviceCharacteristics();
		console.log('found characters -->', characters);
		await this.notifyBLECharacteristicValueChange();
	}

	async connBleAndNotifyForAndroid(deviceId) {
		await this.doAuthorize();
		await this.openBluetoothAdapter();
		await this.createBLEConnection(deviceId);
		// await this.setBLEMTU(120);
		await this.notifyBLECharacteristicValueChange();
	}


	async connBleAndNotifyForIos(deviceId) {
		await this.doAuthorize();
		await this.openBluetoothAdapter();
		const device = await this.startDiscoveryPromise(deviceId);
		await this.createBLEConnection(deviceId);
		await this.getBLEDeviceServices();
		await this.getBLEDeviceCharacteristics();
		this.notifyBLECharacteristicValueChange();
	}

	// DFU升级
	connDFUAndNotify(deviceId) {
		return new Promise(async (resolve, reject) => {
			await this.doAuthorize();
			await this.openBluetoothAdapter();
			const timer = setTimeout(() => {
				if (timer) clearTimeout(timer);
				this.stopBluetoothDevicesDiscovery();
				reject({
					code: BLE_ERR.NO_FOUND_DFU_DEVICE,
					msg: BLE_ERR.NO_FOUND_DFU_DEVICE_MSG
				})
			}, this.searchTimeout)
			this.startDiscoveryCallBack(async (device) => {
				const bleName = device.name.toLocaleUpperCase();
				if (bleName.indexOf("DFU") != -1) {
					console.log('DFU device->', device);
					if (timer) clearTimeout(timer);
					this.stopBluetoothDevicesDiscovery();
					const deviceId = device.deviceId;
					await this.createBLEConnection(deviceId);
					await this.setBLEMTU(120);
					console.log('mtuSize--->', this.mtuSize);
					// DFU的主服务和普通服务不同 需要更改
					const services = await this.getBLEDeviceServices();
					for (const service of services) {
						const uuid = service.uuid;
						if (uuid.indexOf('FE59-') != -1) {
							this.serviceUUID = uuid; // 更改主服务
							break;
						}
					}
					console.log('DFU serviceUUID->', this.serviceUUID);
					// 更改DFU的特征值
					const characters = await this.getBLEDeviceCharacteristics();
					for (const c of characters) {
						if (c.uuid == YOUON_LOCK_CONF.CONTROL_CHARACTER_UUID) {
							this.notifyUUID = YOUON_LOCK_CONF.CONTROL_CHARACTER_UUID;
						}
						if (c.uuid == YOUON_LOCK_CONF.PACKET_CHARACTER_UUID) {
							this.writeUUID = YOUON_LOCK_CONF.PACKET_CHARACTER_UUID;
						}
					}
					console.log('DFU notifyUUID->', this.notifyUUID, ' DFU writeUUID->', this.writeUUID);
					await this.notifyBLECharacteristicValueChange();
					resolve();
				}
			})
		})
	}

	/**
	 * 发送数据
	 * @param cmd 数据包
	 * @param dataByteLen 数据包长度 字节数
	 * @param offset = 0 偏移量
	 */
	async sendData(cmdData, cmdByteLen, offset = 0) {
		do {
			const step = offset + this.mtuSize > cmdByteLen ? cmdByteLen - offset : this.mtuSize;
			const cmd = cmdData.substr(offset * 2, step * 2);
			const hex = util.myStringtoHex(cmd);
			const uint8Array = new Uint8Array(hex);
			const buffer = uint8Array.buffer;
			await this.writeBLECharacteristicValue(buffer);
			console.log("--->write data:" + cmd);
			offset += step;
		} while (offset < cmdByteLen)
	}

	/**
	 * 发送创建command object的命令
	 */
	async send_create_cmd_obj_01() {
		const buffer = new ArrayBuffer(6);
		const dataView = new DataView(buffer);
		dataView.setUint8(0, 0x01); // create命令
		dataView.setUint8(1, 0x01); // create命令的types参数 1:command object 2:data object
		dataView.setUint8(2, 0x8d);
		dataView.setUint8(3, 0x0);
		dataView.setUint8(4, 0x0);
		dataView.setUint8(5, 0x0);
		console.log('send create cmd 01 Command object')
		await this.writeTo90001(buffer);
	}

	/**
	 * 发送创建data object的命令
	 */
	async send_create_data_obj_01(size) {
		const buffer = new ArrayBuffer(6)
		const dataView = new DataView(buffer)
		//写入通道指令 
		dataView.setUint8(0, 0x01)
		dataView.setUint8(1, 0x02)
		dataView.setUint8(2, size[0])
		dataView.setUint8(3, size[1])
		dataView.setUint8(4, 0x0)
		dataView.setUint8(5, 0x0)
		console.log('send create cmd 01 Data object')
		return this.writeTo90001(buffer);
	}


	/**
	 * 发送校验码校验的命令 03
	 */
	async send_checksum_03() {
		const buffer = new ArrayBuffer(1);
		const dataView = new DataView(buffer);
		dataView.setUint8(0, 0x03); // 写入通道指令
		console.log('send calculate checksum cmd 03')
		this.writeTo90001(buffer); // 向90001写入数据
	}

	/**
	 * 发送执行命令 
	 */
	async send_execute_04() {
		const buffer = new ArrayBuffer(1);
		const dataView = new DataView(buffer);
		dataView.setUint8(0, 0x04);
		console.log('send execute cmd 04')
		await this.writeTo90001(buffer); // 向9001发送04执行命令
	}

	/**
	 * 发送一条Command object的06命令 也就是select命令 
	 * select命令需要传递Type参数  01:Command object  02:Data object
	 */
	async send_select_cmd_obj_06() {
		const buffer = new ArrayBuffer(2);
		const dataView = new DataView(buffer);
		dataView.setUint8(0, 0x06);
		dataView.setUint8(1, 0x01); // 01:Command object
		console.log('send select cmd 01 Command object')
		await this.writeTo90001(buffer);
	}
	/**
	 * 发送一条Data object的select的02指令
	 * select命令需要传递Type参数  01:Command object  02:Data object
	 */
	async send_select_data_obj_06() {
		const buffer = new ArrayBuffer(2);
		const dataView = new DataView(buffer);
		dataView.setUint8(0, 0x06);
		dataView.setUint8(1, 0x02); // 02:Data object
		console.log('send select cmd 02 Data object')
		await this.writeTo90001(buffer); // 向90001写入通道指令数据
	}

	/**
	 * 写入 dat包数据
	 */
	async writeDatData(cmdData, datSize, offset = 0) {
		do {
			const step = offset + this.mtuSize > datSize ? datSize - offset : this.mtuSize;
			console.log('offset', offset, 'step', step, 'datSize', datSize)
			const uint8Array = new Uint8Array(cmdData, offset, step);
			let hex = "";
			for (let i in uint8Array) {
				const num = uint8Array[i];
				if (num < 16) {
					hex += '0'
				}
				hex += num.toString(16)
			}
			console.log("--->write dat data:" + hex);
			const writeBuffer = util.bufferFromHex(hex);
			await this.writeTo90002(writeBuffer); // 向90002写入数据		
			offset = offset + step;
		} while (offset < datSize)
	}

	/**
	 * 写入bin包的数据
	 */
	async writeBinData(pack, binSize, offset = 0) {
		do {
			const step = offset + this.mtuSize > binSize ? binSize - offset : this.mtuSize;
			const uint8Array = new Uint8Array(pack, offset, step);
			let hex = "";
			for (let i in uint8Array) {
				const num = uint8Array[i];
				if (num < 16) {
					hex += '0'
				}
				hex += num.toString(16)
			}
			// console.log("--->write bin data:" + hex);
			const writeBuffer = util.bufferFromHex(hex);
			await this.writeTo90002(writeBuffer); // 向90002写入数据		
			offset = offset + step;
		} while (offset < binSize)
		this.send_checksum_03();
	}


	disConnAndClose() {
		try {
			this.closeBLEConnection();
			this.closeBluetoothAdapter();
		} catch (err) {
			console.log(err.msg)
		}
	}


}